package com.travel.sight.service.impl;

import com.alibaba.fastjson.JSON;
import com.travel.common.oss.OssUploadTo;
import com.travel.common.to.UpdateUserAttractionWeightTo;
import com.travel.common.to.UpdateUserTagWeightTo;
import com.travel.common.to.UserBehaviorWeightTo;
import com.travel.common.utils.R;
import com.travel.common.vo.MemberRespVo;
import com.travel.sight.entity.AttractionInfoEntity;
import com.travel.sight.entity.CollectionEntity;
import com.travel.sight.feign.RecommendFeignService;
import com.travel.sight.feign.ThirdpartyFeignService;
import com.travel.sight.service.AttractionInfoService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Service;

import java.io.File;
import java.io.IOException;
import java.time.LocalDate;
import java.time.format.DateTimeFormatter;
import java.util.Date;
import java.util.List;
import java.util.Map;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.travel.common.utils.PageUtils;
import com.travel.common.utils.Query;

import com.travel.sight.dao.CommentDao;
import com.travel.sight.entity.CommentEntity;
import com.travel.sight.service.CommentService;
import org.springframework.web.multipart.MultipartFile;

import static com.travel.common.constant.AuthServerConstant.LOGIN_USER;


@Service("commentService")
public class CommentServiceImpl extends ServiceImpl<CommentDao, CommentEntity> implements CommentService {

    @Autowired
    ThirdpartyFeignService thirdpartyFeignService;

    @Autowired
    StringRedisTemplate redisTemplate;

    @Autowired
    RecommendFeignService recommendFeignService;

    @Autowired
    AttractionInfoService attractionInfoService;

    @Override
    public PageUtils queryPage(Map<String, Object> params) {
        IPage<CommentEntity> page = this.page(
                new Query<CommentEntity>().getPage(params),
                new QueryWrapper<CommentEntity>()
        );

        return new PageUtils(page);
    }

    /**
     * 获取景点的评论列表
     * @param attractionId
     * @return
     */
    @Override
    public List<CommentEntity> getCommentList(Integer attractionId) {
        List<CommentEntity> commentList = this.baseMapper.selectList(new QueryWrapper<CommentEntity>().eq("attraction_id", attractionId));
        return commentList;
    }

    /**
     * 获取该用户评论的次数
     * @param userId
     * @return
     */
    @Override
    public Integer getCommentNumByUserId(Integer userId) {
        return this.baseMapper.selectCount(new QueryWrapper<CommentEntity>().eq("user_id",userId));
    }

    /**
     * 保存评论
     * @param content：内容
     * @param score：评分
     * @param imageFile：图片文件
     * @param attractionId：景点id
     */
    @Override
    public void saveComment(String content, Integer score, MultipartFile imageFile, Integer attractionId,Integer userId) throws Exception {
        System.out.println("content "+content);
        System.out.println("score "+score);
        System.out.println("attractionId "+attractionId);

        CommentEntity entity = new CommentEntity();

        //1. 保存上传的图片到本地
        if (imageFile != null && !imageFile.isEmpty()) {
            String filename = imageFile.getOriginalFilename();
            String filepath = "C:\\Users\\练晓文\\Desktop\\图片\\temp\\" + filename;
            imageFile.transferTo(new File(filepath));

            // 获取该文件在本地的全路径
            String localFilePath = new File(filepath).getAbsolutePath();
            System.out.println("文件在本地的全路径：" + localFilePath);

            //2. 远程调用travel-third-party，上传图片到oss
            OssUploadTo ossUploadTo = new OssUploadTo();
            ossUploadTo.setLocalFilePath(localFilePath);
            ossUploadTo.setObjectName(filename);

            thirdpartyFeignService.PostObject(ossUploadTo);

            //保存到oos的图片路径格式： https://wen-travel.oss-cn-guangzhou.aliyuncs.com/2024-01-30/千岛湖.jpg
            LocalDate today = LocalDate.now();
            DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd");
            String date = today.format(formatter);

            String imageUrl = "https://wen-travel.oss-cn-guangzhou.aliyuncs.com/"+ date + "/" + filename;

            entity.setImageUrl(imageUrl);
            System.out.println("imageUrl "+imageUrl);
        }

        //2. redis更新评论数  attraction_info:44:comment_num
        String key = "attraction_info:"+attractionId+":comment_num";
        String s = redisTemplate.opsForValue().get(key);
        if(s != null){
            redisTemplate.opsForValue().increment(key);
        }else{
            redisTemplate.opsForValue().set(key,"1");
        }


        //3. mysql中添加评论操作
        entity.setAttractionId(attractionId);
        entity.setContent(content);
        entity.setScore(score);
        entity.setUserId(userId);
        entity.setAddTime(new Date());
        entity.setUpdateTime(new Date());

        this.baseMapper.insert(entity);



    }

    /**
     * 1. 更新景点score
     * 2. 更新用户对该景点的权重
     * 3. 更新用户对景点标签的权重
     * @param attractionId
     * @param userId
     */
    @Override
    public void updateAfterComment(Integer attractionId, Integer userId) {
        UserBehaviorWeightTo weight = recommendFeignService.getUserBehaviorWeight();
        Double commentWeight = weight.getCommentWeight();

        //1. 计算并更新score（redis）
        //评分计算公式：(点击数/最大点击数 × 0.1 + 点赞数/最大点赞数 × 0.3 + 收藏数/最大收藏数 × 0.3 + 评论数/最大评论数 ×0.3 ) ×100
        //1.1 从redis中获取 最大点击数、最大点赞数、最大收藏数、最大评论数
        String maxClickKey = "max_value:click_num";
        String maxLikeKey = "max_value:like_num";
        String maxCollectionKey = "max_value:collection_num";
        String maxCommentKey = "max_value:comment_num";

        Integer maxClick = Integer.valueOf(redisTemplate.opsForValue().get(maxClickKey));
        Integer maxLike = Integer.valueOf(redisTemplate.opsForValue().get(maxLikeKey));
        Integer maxCollection = Integer.valueOf(redisTemplate.opsForValue().get(maxCollectionKey));
        Integer maxComment = Integer.valueOf(redisTemplate.opsForValue().get(maxCommentKey));

        //1.2 获取当前景点的 点击数、点赞数、收藏数、评论数（从redis获取，最新的）
        String clickKey = "attraction_info:"+attractionId+":click_num";
        String likeKey = "attraction_info:"+attractionId+":like_num";
        String collectionKey = "attraction_info:"+attractionId+":collection_num";
        String commentKey = "attraction_info:"+attractionId+":comment_num";

        Integer clickNum = Integer.valueOf(redisTemplate.opsForValue().get(clickKey));
        Integer likeNum = Integer.valueOf(redisTemplate.opsForValue().get(likeKey));
        Integer collectionNum = Integer.valueOf(redisTemplate.opsForValue().get(collectionKey));
        Integer commentNum = Integer.valueOf(redisTemplate.opsForValue().get(commentKey));

        //1.3 计算并更新score（redis）
        // 计算新的score值
        Double newScore = (clickNum.doubleValue() / maxClick.doubleValue() * 0.1 + likeNum.doubleValue() / maxLike.doubleValue() * 0.3 +
                collectionNum.doubleValue() / maxCollection.doubleValue() * 0.3 + commentNum.doubleValue() / maxComment.doubleValue() * 0.3) * 100;
        System.out.println("计算得到新的score为 "+newScore);

        String scoreKey = "attraction_info:"+attractionId+":score";
        redisTemplate.opsForValue().set(scoreKey,String.valueOf(newScore));

        //2. 更新用户对该景点的权重
        AttractionInfoEntity byId = attractionInfoService.getById(attractionId);

        UpdateUserAttractionWeightTo attractionWeightTo = new UpdateUserAttractionWeightTo();
        attractionWeightTo.setAttractionId(byId.getAttractionId());
        attractionWeightTo.setName(byId.getName());
        attractionWeightTo.setTag(byId.getTag());
        attractionWeightTo.setWeight(commentWeight);

        R r1 = recommendFeignService.updateUserAttractionWeight(attractionWeightTo,userId);
        if(r1.getCode() == 0){
            System.out.println("更新用户对该景点的权重 成功");
        }else{
            System.out.println("更新用户对该景点的权重 失败");
        }

        //3. 更新用户对景点标签的权重
        UpdateUserTagWeightTo tagWeightTo = new UpdateUserTagWeightTo();
        tagWeightTo.setTagName(byId.getTag());
        tagWeightTo.setWeight(commentWeight);

        R r2 = recommendFeignService.updateUserTagWeight(tagWeightTo,userId);
        if(r2.getCode() == 0){
            System.out.println("更新用户对景点标签的权重 成功");
        }else{
            System.out.println("更新用户对景点标签的权重 失败");
        }

    }

}